<template>

  <div class="record-box">
    <div style="display: flex; width: 100%; align-items: center">
      <div v-if="state===0 || state ===1 || playing" class="line-box">
        <div :style="`height: ${line[0]}%`" class="line-item"/>
        <div :style="`height: ${line[1]}%`" class="line-item"/>
        <div :style="`height: ${line[2]}%`" class="line-item"/>
      </div>

      <div v-if="state===2 && !playing" class="line-box">
        <i class="el-icon-success" style="color: #1aac1a; font-size: 20px"/>
      </div>

      <div class="title-box"><span>{{ msg }}</span></div>
    </div>
    <div style="font-size: 24px">{{ formatSec() }}</div>
    <div style="margin-top: 15px">
      <el-button
        :disabled="state===2"
        :type="state===1?'danger':'primary'"
        size="large"
        icon="el-icon-mic"
        style="font-size: 32px"
        circle
        @click="startRecord" />
    </div>
    <div class="opt-box">
      <el-button
        :disabled="state!==2"
        :type="state===2?'danger':'default'"
        plain
        icon="el-icon-delete-solid"
        circle
        @click="clearRecord" />
      <el-button
        :disabled="state!==2"
        :type="state===2?'primary':'default'"
        :icon="playing?'el-icon-video-pause':'el-icon-caret-right'"
        plain
        circle
        @click="playRecord" />
      <el-button
        :disabled="state!==2"
        :loading="loading"
        :type="state===2?'success':'default'"
        plain
        icon="el-icon-upload"
        circle
        @click="saveRecord"/>
    </div>
  </div>
</template>

<script>
import Recorder from 'js-audio-recorder'
import { uploadFile } from '@/utils/upload'

const recorder = new Recorder({
  sampleBits: 16, // 采样位数，支持 8 或 16，默认是16
  sampleRate: 48000, // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000
  numChannels: 1 // 声道，支持 1 或 2， 默认是1
})

export default {
  name: 'Record',
  props: {
    value: String
  },
  data() {
    return {
      line: [30, 65, 100],
      msg: '准备录音..',
      state: 0, // 0准备就绪，1录音中，2录音完成
      loading: false,
      timer: null,
      seconds: 0,
      fileObj: null,
      playTimer: null,
      playing: false
    }
  },

  beforeDestroy() {
    recorder.destroy()
  },

  mounted() {
    // 播放
    recorder.onplay = () => {
      this.playing = true
      this.msg = '录音播放中..'
      this.playRun()
    }

    // 停止播放
    recorder.onstopplay = () => {
      this.playing = false
      this.msg = this.state === 0 ? '准备录音..' : '录音已完成..'
      clearInterval(this.playTimer)
    }

    // 播放结束
    recorder.onplayend = () => {
      this.playing = false
      this.msg = this.state === 0 ? '准备录音..' : '录音已完成..'
      clearInterval(this.playTimer)
    }
  },

  methods: {

    // 格式显示
    formatSec() {
      let min = 0
      let sec = 0
      if (this.seconds >= 60) {
        min = parseInt((this.seconds / 60))
        sec = this.seconds % 60
      } else {
        sec = this.seconds
      }
      return (min<10 ? '0' + min : min) + ':' + (sec<10 ? '0' + sec : sec)
    },

    // 单纯为了显示一个图标效果
    playRun() {
      this.playTimer = setInterval(() => {
        for (let i = 0; i<this.line.length; i++) {
          const v = this.line[i]
          if (v < 100) {
            this.line[i] = v + 5
          } else {
            this.line[i] = 0
          }
        }
        this.$forceUpdate()
      }, 100)
    },

    // 清理数据
    clearRecord() {
      // 就绪
      this.state = 0
      this.seconds = 0
      this.fileObj = null
      this.msg = '准备录音..'
      if (this.playing) {
        recorder.stopPlay()
      }
    },

    // 播放或暂停录音
    playRecord() {
      if (this.state === 2) {
        if (!this.playing) {
          recorder.play()
        } else {
          recorder.stopPlay()
        }
      }
    },

    // 开始录音
    startRecord: function() {
      // 正在录音则停止
      if (this.state === 1) {
        this.stopRecord()
        return
      }
      recorder.start().then(() => {
        this.msg = '正在录音中..'
        this.state = 1
        this.playRun()
        this.timer = setInterval(() => {
          this.seconds += 1
        }, 1000)
      },
      (error) => {
        this.$message.error(`${error.name} : ${error.message}`)
      })
    },

    // 录音结束
    stopRecord: function() {
      recorder.stop()
      // 获得录音文件
      this.fileObj = recorder.getWAVBlob()
      // 停止计时
      clearInterval(this.timer)
      clearInterval(this.playTimer)
      // 录音完成
      this.msg = '录音已完成..'
      this.state = 2
    },

    // 上传和保存录音文件
    saveRecord() {
      this.loading = true
      const file = new window.File([this.fileObj], 'record.wav', { type: 'audio/wav' })
      this.msg = '录音上传中..'
      // 上传文件
      uploadFile(file).then(res => {
        this.loading = false
        this.$emit('input', res)
        this.$emit('success', res)
        // 重置录音机
        setTimeout(() => {
          this.clearRecord()
        }, 1000)
      }, err => {
        console.log(err)
      })
    }

  }
}
</script>

<style scoped>
.record-box{
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: #fff;
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  width: 460px;
  height: 220px;
  padding: 20px;
}

.title-box{
  display: flex;
  width: 100%;
  align-items: center;
  height: 20px;
  padding-left: 5px;
}

.line-box{
  height: 16px;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  width: 19px;
}

.line-item{
  background: #0A84FF;
  width: 5px;
}

.opt-box{
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 200px;
  margin-top: 20px;
}

.opt-box button{
  font-size: 18px;
}
</style>
